﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HMIS.FrameWork.DomainBase;
using NHibernate;
using NHibernate.Criterion;
using HMIS.FrameWork.Repository.NHb;

namespace HMIS.FrameWork.Repository.Nhb
{
	public class RepositoryNhbImpl<T> : IRepository<T> where T : BaseEntity
	{
		protected virtual ISession Session
		{
			get { return SessionBuilder.CreateSession(); }
		}
		#region IRepository<T> 成员

		/// <summary>
		/// 读取信息。如果是空返回异常
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public virtual T Load(string id)
		{
			try
			{
				T reslut = Session.Load<T>(id);
				if (reslut == null)
					throw new RepositoryException("返回实体为空");
				else
					return reslut;
			}
			catch (Exception ex)
			{
				throw new RepositoryException("获取实体失败", ex);
			}
		}

		/// <summary>
		/// 读取信息。返回null
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public virtual T Get(string id)
		{
			try
			{
				T reslut = Session.Get<T>(id);
				return reslut;
			}
			catch (Exception ex)
			{
				throw new RepositoryException("获取实体失败", ex);
			}
		}

		public virtual T GetOrNull(string id)
		{
			try
			{
				T reslut = Session.Get<T>(id);
				return reslut;
			}
			catch (Exception ex)
			{
				throw new RepositoryException("获取实体失败", ex);
			}
		}

		public virtual IList<T> GetAll()
		{
			return Session.CreateCriteria<T>()
				.AddOrder(Order.Asc("CreateTime"))
				.List<T>();
		}

		public virtual void SaveOrUpdate(T entity)
		{
			try
			{
				Session.Transaction.Begin();
				Session.SaveOrUpdate(entity);
				Session.Flush();
				Session.Transaction.Commit();
			}
			catch (Exception ex)
			{
				Session.Transaction.Rollback();
				throw new RepositoryException("插入实体失败", ex);
			}
		}

		public virtual void Update(T entity)
		{
			try
			{
				Session.Transaction.Begin();
				Session.Update(entity);
				Session.Flush();
				Session.Transaction.Commit();
			}
			catch (Exception ex)
			{
				Session.Transaction.Rollback();
				throw new RepositoryException("更新实体失败", ex);
			}
		}

		public virtual void PhysicsDelete(string id)
		{
			try
			{
				var entity = Get(id);
				Session.Delete(entity);
				Session.Flush();
			}
			catch (System.Exception ex)
			{
				throw new RepositoryException("物理删除实体失败", ex);
			}
		}

		public virtual void Delete(string id)
		{
			try
			{
				var entity = Get(id);
				entity.IsDelete = true;
				Update(entity);
			}
			catch (System.Exception ex)
			{
				throw new RepositoryException("删除实体失败", ex);
			}
		}
		#endregion

		//判断字段的值是否存在 如果是插入id赋值-1或者new Guid,如果是修改id赋值 要修改项的值
		public virtual bool IsFieldExist(string fieldName, string fieldValue, string id, string where)
		{
			if (!string.IsNullOrEmpty(where))
				where = @" and " + where;
			var query = Session.CreateQuery(
				string.Format(@"select count(*) from {0} as o where o.{1}='{2}' and o.Id<>'{3}'" + where,
				typeof(T).Name,
				fieldName,
				fieldValue, id));

			return query.UniqueResult<long>() > 0;
		}

		//处理ExtJs字段过滤
		public string GetHqlstrByExtFilter(List<DataFilter> filters, string a)
		{
			if (filters == null)
				return string.Empty;
			StringBuilder result = new StringBuilder();
			//type=string
			var stringList = from f in filters where f.type == "string" select f;
			foreach (var i in stringList)
			{
				result.Append(a + "." + i.field + " like " + "'%" + i.value + "%'" + " and ");
			}
			//type=boolean
			var booleanList = from f in filters where f.type == "boolean" select f;
			foreach (var i in booleanList)
			{
				result.Append(a + "." + i.field + "=" + i.value + " and ");
			}
			//type=numeric
			var numericList = from f in filters where f.type == "numeric" group f by f.field into g select g;
			foreach (var i in numericList)
			{
				result.Append("( ");
				string iiStr = string.Empty;
				foreach (var ii in i)
				{
					iiStr += a + "." + ii.field + GetComparison(ii.comparison) + ii.value + " and ";
				}
				result.Append(iiStr.Substring(0, iiStr.Length - 4));
				result.Append(" )");
				result.Append(" and ");
			}
			//type=date
			var dateList = from f in filters where f.type == "date" group f by f.field into g select g;
			foreach (var i in dateList)
			{
				result.Append("( ");
				string iiStr = string.Empty;
				foreach (var ii in i)
				{
					//todo .. sqlserver 不支持 to_date

					// oracle
					//iiStr += a + "." + ii.field + GetComparison(ii.comparison) + " to_date('" + ii.value + "', 'mm/dd/yyyy')" + " and ";
					// sqlserver
					iiStr += a + "." + ii.field + GetComparison(ii.comparison) + " cast('" + ii.value + "' as datetime)" + " and ";
				}
				result.Append(iiStr.Substring(0, iiStr.Length - 4));
				result.Append(" )");
				result.Append(" and ");
			}
			//type=list  :["1","2"]
			var listList = from f in filters where f.type == "list" select f;
			foreach (var i in listList)
			{
				result.Append(a + "." + i.field + " in " + i.value.Replace("[", "( ").Replace("]", " )").Replace("\"", "'") + " and ");
			}

			return result.ToString().Substring(0, result.Length - 4);
		}

		private string GetComparison(string comparison)
		{
			string res = string.Empty;
			switch (comparison)
			{
				case "lt":
					res = "<";
					break;
				case "gt":
					res = ">";
					break;
				case "eq":
					res = "=";
					break;
			}
			return res;
		}
	}
}
